package mi.payment.transaction;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.sunmi.pay.hardware.aidl.AidlErrorCode;
import com.sunmi.pay.hardware.aidl.SPErrorCode;
import com.sunmi.pay.hardware.aidl.bean.CardInfo;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.bean.EMVCandidateV2;
import com.sunmi.pay.hardware.aidlv2.bean.EMVTransDataV2;
import com.sunmi.pay.hardware.aidlv2.bean.PinPadConfigV2;
import com.sunmi.pay.hardware.aidlv2.bean.PinPadDataV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVListenerV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVOptV2;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadListenerV2;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadOptV2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import lainey.ui.dialog.ListDialog;
import lainey.ui.utils.LogUtil;
import lainey.ui.widget.TitleView;
import mi.payment.CardType;
import mi.payment.Constant;
import mi.payment.MyApplication;
import mi.payment.R;
import mi.payment.bean.db.TradeData;
import mi.payment.constants.Params;
import mi.payment.db.PayDetailModel;
import mi.payment.db.dao.PayDetail;
import mi.payment.transaction.sale.ConsumeSwingCardActivity;
import mi.payment.ui.base.FixPasswordKeyboard;
import mi.payment.ui.base.PageRoute;
import mi.payment.ui.base.ParentActivity;
import mi.payment.ui.base.PasswordEditText;
import mi.payment.utils.ByteUtil;
import mi.payment.utils.Config;
import mi.payment.utils.MoneyUtils;
import mi.payment.utils.NetUtils;
import mi.payment.utils.UIUtils;
import mi.payment.utils.iso8583.TLV;
import mi.payment.utils.iso8583.TLVUtils;
import mi.payment.utils.iso8583.Utils;
import sunmi.payment.L3.L3BroadcastHelper;
import sunmi.payment.L3.L3ErrorCode;

public abstract class V2InputPasswordActivity extends ParentActivity {

    private int mWidth = 239;                       // 密码键盘单个item宽度
    private int mHeight = 130;                      // 密码键盘单个item高度
    private int mInterval = 1;                      // 线间隔
    private int[] mKeyboardCoordinate = {0, 661};   // 密码键盘第一个button左顶点位置（绝对位置）
    private int mCancelWidth = 112;                 // 取消键宽度
    private int mCancelHeight = 112;                // 取消键高度
    private int[] mCancelCoordinate = {0, 48};      // 取消键左顶点位置（绝对位置）

    private View mBtnOK;
    private View mBackView;
    private View mLineView;
    private TextView mTvCard;
    private TextView mTvAmount;
    private View mCardNumberView;
    private PasswordEditText mPasswordEditText;
    private FixPasswordKeyboard mFixPasswordKeyboard;

    private EMVOptV2 mEMVOptV2;
    private PinPadOptV2 mPinPadOptV2;

    private ListDialog mListDialog;

    private String mTag9F06Value;
    private int mPinType = 0;               // PIN类型标识(0是联机PIN，1是脱机PIN)
    private boolean isForceInputPWD = true; // 是否输入密码 默认需要输入密码

    public TextView mTvTitle;
    public TradeData mTradeData;
    private PayDetail mPayDetail;

    public abstract void onStartOnline();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.consume_activity_input_pwd);
        initView();
    }

    private void initView() {
        mTradeData = Params.getTradeData();
        mPayDetail = mTradeData.getPayDetail();

        mEMVOptV2 = MyApplication.getInstance().mEMVOptV2;
        mPinPadOptV2 = MyApplication.getInstance().mPinPadOptV2;

        TitleView titleView = findViewById(R.id.title_view);
        mTvTitle = titleView.getCenterTextView();
        mBackView = titleView.getLeftImageView();
        titleView.setLeftImageOnClickListener(
                v -> onBackPressed()
        );

        mBtnOK = findViewById(R.id.mb_ok);
        mTvAmount = findViewById(R.id.tv_money);
        mTvCard = findViewById(R.id.tv_card_num);
        mPasswordEditText = findViewById(R.id.passwordEditText);
        mFixPasswordKeyboard = findViewById(R.id.fixPasswordKeyboard);

        mBtnOK.setOnClickListener(
                v -> handleTransactionProcess()
        );

        mBtnOK.setVisibility(View.GONE);
        mPasswordEditText.setVisibility(View.GONE);
        mFixPasswordKeyboard.setVisibility(View.GONE);
        mLineView = findViewById(R.id.line_card_num);
        mCardNumberView = findViewById(R.id.view_card_num);

        mBtnOK.setOnClickListener(this);

        String text = getString(R.string.money_only_symbol) + MoneyUtils.longCent2DoubleMoneyStr(mPayDetail.amount);
        mTvAmount.setText(text);

        hideCardNo(false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        UIUtils.screenFinancialModel();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        dismissListDialog();
        if (Params.sL3Params == null) UIUtils.screenMonopoly(-1);
        mHandler.removeCallbacksAndMessages(null);
    }

    @Override
    public void onBackPressed() {
        importPinInputStatus(1);
        handleCallProgram(L3ErrorCode.ERROR_TRADE_CANCEL);
        super.onBackPressed();
    }

    private static final int PIN_CLICK_CANCEL = 1;
    private static final int PIN_CLICK_NUMBER = 2;
    private static final int PIN_CLICK_CONFIRM = 3;
    private static final int PIN_ERROR = 4;

    private static final int EMV_APP_SELECT = 5;
    private static final int EMV_APP_FINAL_SELECT = 6;
    private static final int EMV_CONFIRM_CARD_NO = 7;
    private static final int EMV_CERT_VERIFY = 8;
    private static final int EMV_SIGNATURE = 9;
    private static final int EMV_SHOW_PIN_PAD = 10;
    private static final int EMV_ONLINE_PROCESS = 11;
    private static final int EMV_ERROR = 12;

    private Looper mLooper = Looper.getMainLooper();
    private final Handler mHandler = new Handler(mLooper) {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PIN_CLICK_NUMBER:
                    showPasswordView(msg.arg1);
                    break;
                case PIN_CLICK_CONFIRM:
                    if (mPayDetail.PINCipher != null && mPayDetail.PINCipher.length() > 0) {
                        importPinInputStatus(0);
                    } else {
                        importPinInputStatus(2);
                    }
                    break;
                case PIN_CLICK_CANCEL:
                    importPinInputStatus(1);
                    break;
                case PIN_ERROR:
                    importPinInputStatus(3);
                    handleTransactionFail(msg.arg1);
                    break;

                case EMV_APP_SELECT:
                    List<EMVCandidateV2> list = ( List<EMVCandidateV2> ) msg.obj;
                    showListDialog(list);
                    break;
                case EMV_APP_FINAL_SELECT:
                    importAppFinalSelectStatus(0);
                    break;
                case EMV_CONFIRM_CARD_NO:
                    importCardNoStatus(0);
                    break;
                case EMV_CERT_VERIFY:
                    importCertStatus(0);
                    break;
                case EMV_SIGNATURE:
                    importSignatureStatus(0);
                    break;
                case EMV_SHOW_PIN_PAD:
                    initPinPad();
                    break;
                case EMV_ONLINE_PROCESS:
                    handleTransactionProcess();
                    break;
                case EMV_ERROR:
                    handleTransactionFail(msg.arg1);
                    break;
            }
        }

    };

    public void startTransactionProcess() {
        showLoadingDialog(R.string.load);
        getKSN();

        // 手输卡号或者磁卡时 不走emv流程 直接调用密码键盘
        boolean noCard = CardType.NO_CARD.getValue() == mPayDetail.cardType || CardType.MAGNETIC.getValue() == mPayDetail.cardType;
        if (noCard && isForceInputPWD == true) {
            initPinPad();
            return;
        }
        if (noCard && isForceInputPWD == false) {
            showNoPasswordView();
            return;
        }

        try {
            if (isForceInputPWD) {
                transactProcess(1);
            } else {
                showNoPasswordView();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否输入密码
     */
    public void setForceInputPWD(boolean isForce) {
        isForceInputPWD = isForce;
        if (isForceInputPWD) {
            findViewById(R.id.tv_hint).setVisibility(View.VISIBLE);
        } else {
            findViewById(R.id.tv_hint).setVisibility(View.GONE);
        }
    }

    public void showAmountView(boolean isShow) {
        if (isShow) {
            mLineView.setVisibility(View.VISIBLE);
            mTvAmount.setVisibility(View.VISIBLE);
        } else {
            mLineView.setVisibility(View.GONE);
            mTvAmount.setVisibility(View.GONE);
        }
    }

    /**
     * 是否显示卡号
     */
    public void showCardNoView(boolean isShow) {
        if (isShow) {
            mLineView.setVisibility(View.VISIBLE);
            mCardNumberView.setVisibility(View.VISIBLE);
        } else {
            mLineView.setVisibility(View.GONE);
            mCardNumberView.setVisibility(View.GONE);
        }
    }

    /**
     * 是否隐藏卡号
     */
    public void hideCardNo(boolean hide) {
        if (hide) {
            String text = interceptCardNo(mPayDetail.CardNo);
            mTvCard.setText(text);
        } else {
            mTvCard.setText(mPayDetail.CardNo);
        }
    }

    /**
     * 获取KSN
     */
    private void getKSN() {
        try {
            byte[] dataOut = new byte[10];
            int result = MyApplication.getInstance().mSecurityOptV2.dukptCurrentKSN(Constant.indexDuKpt, dataOut);
            if (result == 0) {
                String ksnStr = ByteUtil.bytes2HexStr(dataOut);
                LogUtil.e(Constant.TAG, "ksnStr: " + ksnStr);
                int length = ksnStr.length();
                ksnStr = ksnStr.substring(length - 16, length);
                mPayDetail.tempKSN = ksnStr;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initEmvProcess() {
        try {
            // 设置普通的TLV数据
            String[] tags = {"5F2A", "5F36"};
            String[] values = {"0643", "00"};
            mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tags, values);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private void transactProcess(int flowType) {
        LogUtil.e(Constant.TAG, "***************************************************************");
        LogUtil.e(Constant.TAG, "****************************Start Process**********************");
        LogUtil.e(Constant.TAG, "***************************************************************");

        LogUtil.e(Constant.TAG, "transactProcess");
        try {
            // 初始化EMV流程
            mEMVOptV2.initEmvProcess();

            EMVTransDataV2 emvTransData = new EMVTransDataV2();
            emvTransData.amount = mPayDetail.amount + "";
            emvTransData.transType = "20";
            // flow - 流程类型，0x01：标准的授权过程；0x02：简易流程；0x03 qPass
            emvTransData.flowType = flowType;
            emvTransData.cardType = mPayDetail.cardType;
            mEMVOptV2.transactProcess(emvTransData, mEMVListener);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initPinPad() {
        try {
            PinPadConfigV2 config = new PinPadConfigV2();
            config.setMaxInput(12);
            config.setMinInput(4);
            config.setPinPadType(1);
            config.setAlgorithmType(0);
            config.setPinType(mPinType);
            config.setTimeout(60 * 1000);
            config.setOrderNumKey(false);

            config.setKeySystem(1);
            config.setPinKeyIndex(Constant.indexDuKpt);

            // 获取panBlock
            int length = mPayDetail.CardNo.length();
            byte[] panBytes = mPayDetail.CardNo.substring(length - 13, length - 1).getBytes("US-ASCII");
            config.setPan(panBytes);

            String result = mPinPadOptV2.initPinPad(config, mPinPadListener);
            LogUtil.e(Config.TAG, "result:" + result);

            getKeyboardCoordinate(result);

            mPasswordEditText.clearText();
            mFixPasswordKeyboard.setKeepScreenOn(true);
            mFixPasswordKeyboard.setKeyBoard(result);

            dismissLoadingDialog();
            mPasswordEditText.setVisibility(View.VISIBLE);
            mFixPasswordKeyboard.setVisibility(View.VISIBLE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getKeyboardCoordinate(final String keyBoardText) {
        mFixPasswordKeyboard.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {

                    @Override
                    public void onGlobalLayout() {
                        mFixPasswordKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        TextView textView = mFixPasswordKeyboard.getKey_0();
                        textView.getLocationOnScreen(mKeyboardCoordinate);
                        mWidth = textView.getWidth();
                        mHeight = textView.getHeight();
                        mInterval = 1;
                        mBackView.getLocationOnScreen(mCancelCoordinate);
                        mCancelWidth = mBackView.getWidth();
                        mCancelHeight = mBackView.getHeight();
                        importPinPadData(keyBoardText);
                    }

                }
        );
    }

    /**
     * 导入键盘坐标
     */
    private void importPinPadData(String text) {
        PinPadDataV2 pinPadData = new PinPadDataV2();
        pinPadData.numX = mKeyboardCoordinate[0];
        pinPadData.numY = mKeyboardCoordinate[1];
        pinPadData.numW = mWidth;
        pinPadData.numH = mHeight;
        pinPadData.lineW = mInterval;
        pinPadData.cancelX = mCancelCoordinate[0];
        pinPadData.cancelY = mCancelCoordinate[1];
        pinPadData.cancelW = mCancelWidth;
        pinPadData.cancelH = mCancelHeight;
        pinPadData.lineW = 0;
        pinPadData.rows = 4;
        pinPadData.clos = 3;
        keyMap(text, pinPadData);
        try {
            mPinPadOptV2.importPinPadData(pinPadData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private EMVListenerV2 mEMVListener = new EMVListenerV2.Stub() {

        @Override
        public void onWaitAppSelect(List<EMVCandidateV2> appNameList, boolean isFirstSelect) throws RemoteException {
            LogUtil.e(Constant.TAG, "onWaitAppSelect isFirstSelect:" + isFirstSelect);
            mHandler.obtainMessage(EMV_APP_SELECT, appNameList).sendToTarget();
        }

        @Override
        public void onAppFinalSelect(String tag9F06Value) throws RemoteException {
            LogUtil.e(Constant.TAG, "tag9F06Value:" + tag9F06Value);
            mTag9F06Value = tag9F06Value;
            initEmvProcess();

            if (tag9F06Value != null && tag9F06Value.length() > 0) {
                boolean visa = tag9F06Value.startsWith("A000000003");
                boolean master = tag9F06Value.startsWith("A000000004");
                boolean unionPay = tag9F06Value.startsWith("A000000333");
                if (visa) {
                    // VISA - PayWave
                    LogUtil.e(Constant.TAG, "detect VISA card");
                    String[] tagsPayWave = {
                            "DF8124", "DF8125", "DF8126"
                    };
                    String[] valuesPayWave = {
                            "999999999999", "999999999999", "000000000000"
                    };
                    mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYWAVE, tagsPayWave, valuesPayWave);
                } else if (master) {
                    // MasterCard - PayPass
                    LogUtil.e(Constant.TAG, "detect MasterCard card");
                    String[] tagsPayPass = {
                            "DF8117", "DF8118", "DF8119", "DF811F", "DF811E", "DF812C",
                            "DF8123", "DF8124", "DF8125", "DF8126",
                            "DF811B", "DF811D", "DF8122", "DF8120", "DF8121"
                    };
                    String[] valuesPayPass = {
                            "E0", "F8", "F8", "E8", "00", "00",
                            "999999999999", "000000001000", "000000001000", "000000001000",
                            "30", "02", "0000000000", "000000000000", "000000000000"
                    };
                    mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagsPayPass, valuesPayPass);
                } else if (unionPay) {
                    // UnionPay
                    LogUtil.e(Constant.TAG, "detect UnionPay card");
                }
            }

            if (CardType.IC.getValue() == mPayDetail.cardType) {
                String[] tags = {
                        "9F33", "9F09", "DF81FF"
                };
                String[] values = {
                        "E008FF", "0111", "01"
                };
                mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tags, values);
            }

            mHandler.obtainMessage(EMV_APP_FINAL_SELECT, tag9F06Value).sendToTarget();
        }

        @Override
        public void onConfirmCardNo(String cardNo) throws RemoteException {
            LogUtil.e(Constant.TAG, "onConfirmCardNo cardNo:" + cardNo);
            getCardInfo();
            mHandler.obtainMessage(EMV_CONFIRM_CARD_NO).sendToTarget();
        }

        @Override
        public void onRequestShowPinPad(int type, int remainTime) throws RemoteException {
            LogUtil.e(Config.TAG, "requestShowPinPad type:" + type + " remainTime:" + remainTime);
            mPinType = type;
            mHandler.sendEmptyMessage(EMV_SHOW_PIN_PAD);
        }

        @Override
        public void onRequestSignature() throws RemoteException {
            LogUtil.e(Constant.TAG, "signatureStatus");
            mHandler.sendEmptyMessage(EMV_SIGNATURE);
        }

        @Override
        public void onCertVerify(int certType, String certInfo) throws RemoteException {
            LogUtil.e(Constant.TAG, "onCertVerify certType:" + certType + " certInfo:" + certInfo);
            mHandler.obtainMessage(EMV_CERT_VERIFY).sendToTarget();
        }

        @Override
        public void onOnlineProc() throws RemoteException {
            LogUtil.e(Config.TAG, "onProcessEnd");
            getF055Data();
            getPayWaveData();
            mHandler.sendEmptyMessage(EMV_ONLINE_PROCESS);
        }

        @Override
        public void onCardDataExchangeComplete() throws RemoteException {
            LogUtil.e(Config.TAG, "onCardDataExchangeComplete");
        }

        @Override
        public void onConfirmationCodeVerified() throws RemoteException {
            LogUtil.e(Config.TAG, "onConfirmationCodeVerified");

            byte[] outData = new byte[512];
            int len = mEMVOptV2.getTlv(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, "DF8129", outData);
            if (len > 0) {
                byte[] data = new byte[len];
                System.arraycopy(outData, 0, data, 0, len);
                String hexStr = ByteUtil.bytes2HexStr(data);
                LogUtil.e(Constant.TAG, "DF8129: " + hexStr);
            }

            int nfcValue = AidlConstants.CardType.NFC.getValue();
            MyApplication.app.readCardOpt.cardOff(nfcValue);

            runOnUI(
                    () -> {
                        new AlertDialog.Builder(mActivity)
                                .setTitle("See Phone")
                                .setMessage("execute See Phone flow")
                                .setPositiveButton("OK", (dia, which) -> {
                                            dia.dismiss();

                                            String moneyStr = MoneyUtils.longCent2DoubleMoneyStr(mPayDetail.amount);
                                            ConsumeSwingCardActivity.startAction(mActivity, moneyStr);

                                            finish();
                                        }
                                )
                                .show();
                    }
            );
        }

        @Override
        public void onTransResult(int code, String desc) throws RemoteException {
            if (code == -4003 && mTag9F06Value.startsWith("A000000003") && CardType.NFC.getValue() == mPayDetail.cardType) {
                // visa see phone
                onConfirmationCodeVerified();
                return;
            }
            if (code == 0 && isForceInputPWD == false) { // 简易流程
                getF055Data();
                mHandler.sendEmptyMessage(EMV_ONLINE_PROCESS);
            } else if (code == 1) { // 脱机批准
                offlineApproval();
            } else if (code == 2) { // 脱机拒绝
                offlineDenial();
            } else if (code < 0) {
                mHandler.obtainMessage(EMV_ERROR, code, code, desc).sendToTarget();
            }

            LogUtil.e(Constant.TAG, "onTransResult code:" + code + " desc:" + desc);
            LogUtil.e(Constant.TAG, "***************************************************************");
            LogUtil.e(Constant.TAG, "****************************End Process************************");
            LogUtil.e(Constant.TAG, "***************************************************************");
        }

    };

    private PinPadListenerV2 mPinPadListener = new PinPadListenerV2.Stub() {

        @Override
        public void onPinLength(int len) throws RemoteException {
            LogUtil.e(Config.TAG, "onPinLength len:" + len);
            mHandler.obtainMessage(PIN_CLICK_NUMBER, len, 0).sendToTarget();
        }

        @Override
        public void onConfirm(int status, byte[] pinBlock) throws RemoteException {
            LogUtil.e(Config.TAG, "onConfirm status:" + status);
            if (pinBlock != null) {
                String hexStr = Utils.byte2HexStr(pinBlock);
                LogUtil.e(Config.TAG, "hexStr:" + hexStr);
                boolean equals = TextUtils.equals("00", hexStr);
                if (equals) {
                    mPayDetail.PINCipher = "";
                } else {
                    mPayDetail.PINCipher = hexStr;
                }
            }
            // 手输卡号或者磁卡不需要导入Pin 直接联机
            if (CardType.NO_CARD.getValue() == mPayDetail.cardType || CardType.MAGNETIC.getValue() == mPayDetail.cardType) {
                mHandler.sendEmptyMessage(EMV_ONLINE_PROCESS);
            } else {
                mHandler.sendEmptyMessage(PIN_CLICK_CONFIRM);
            }
        }

        @Override
        public void onCancel() throws RemoteException {
            LogUtil.e(Config.TAG, "onCancel");
            mHandler.sendEmptyMessage(PIN_CLICK_CANCEL);
        }

        @Override
        public void onError(int code) throws RemoteException {
            LogUtil.e(Config.TAG, "onError code:" + code);
            mHandler.obtainMessage(PIN_ERROR, code, 0).sendToTarget();
        }

    };

    private void offlineApproval() {
        // TODO
        mPayDetail.tradeAnswerCode = "00";
        mPayDetail.isNeedReversal = false;
        mPayDetail.transactionType = 1;
        mPayDetail.transPlatform = 0;
        PayDetailModel.getInstance().insert(mPayDetail);

        PageRoute.startAction(mActivity, PageRoute.TYPE_CONSUME, mPayDetail);
        finish();
    }

    private void offlineDenial() {
        mPayDetail.tradeAnswerCode = Constant.ANSWER_CODE_DENIAL;
        mPayDetail.isNeedReversal = false;
        mPayDetail.transactionType = 1;
        mPayDetail.transPlatform = 0;
        PayDetailModel.getInstance().insert(mPayDetail);

        PageRoute.startAction(mActivity, PageRoute.TYPE_CONSUME, mPayDetail);
        finish();
    }

    private void handleCallProgram(L3ErrorCode code) {
        if (Params.sL3Params == null) {
            String hint = L3ErrorCode.getMessage(code);
            showToast(hint);
            return;
        }
        sendCloseAppBroadcast();
        L3BroadcastHelper.sendFailedBroadcast(mContext, code);
    }

    private void handleTransactionProcess() {
        boolean connected = NetUtils.isNetworkConnected(mContext);
        LogUtil.e(Config.TAG, "网络连接状态：" + connected);
        if (connected) {
            onStartOnline();
        } else {
            mPayDetail.tradeAnswerCode = Constant.ANSWER_CODE_NETWORK;
            ResultActivity.startAction(this, R.string.consume_im_title, mPayDetail);
            finish();
        }
    }

    private void handleTransactionFail(int code) {
        if (AidlErrorCode.ERROR_INPUT_TIMEOUT.getCode() == code ||
                SPErrorCode.SEC_ERR_PIN_TIMEOUT.getCode() == code) {
            handleCallProgram(L3ErrorCode.ERROR_TRADE_TIMEOUT);
        } else if (AidlErrorCode.EMV_PIN_CANCELED.getCode() == code ||
                SPErrorCode.SEC_ERR_INPUT_CANCEL.getCode() == code) {
            handleCallProgram(L3ErrorCode.ERROR_TRADE_CANCEL);
        } else {
            handleCallProgram(L3ErrorCode.ERROR_TRADE_FAILED);
        }
        finish();
    }

    private void showPasswordView(int len) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) {
            sb.append("*");
        }
        mPasswordEditText.setText(sb);
    }

    private void showNoPasswordView() {
        dismissLoadingDialog();
        mBtnOK.setVisibility(View.VISIBLE);
    }

    private void importAppSelect(int selectIndex) {
        LogUtil.e(Constant.TAG, "importAppSelect selectIndex:" + selectIndex);
        try {
            mEMVOptV2.importAppSelect(selectIndex);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void importAppFinalSelectStatus(int status) {
        LogUtil.e(Constant.TAG, "importAppFinalSelectStatus status:" + status);
        try {
            mEMVOptV2.importAppFinalSelectStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void importCardNoStatus(int status) {
        LogUtil.e(Constant.TAG, "importCardNoStatus status:" + status);
        try {
            mEMVOptV2.importCardNoStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void importCertStatus(int status) {
        LogUtil.e(Constant.TAG, "importCertStatus status:" + status);
        try {
            mEMVOptV2.importCertStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void importSignatureStatus(int status) {
        LogUtil.e(Constant.TAG, "importSignatureStatus status:" + status);
        try {
            mEMVOptV2.importSignatureStatus(status);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * pinTyp PIN类型：0 联机PIN 1 脱机PIN
     * inputResult PIN输入结果 0:处理成功 1:PIN取消 2:PIN跳过 3:PIN故障
     */
    private void importPinInputStatus(int inputResult) {
        LogUtil.e(Constant.TAG, "importPinInputStatus:" + inputResult);
        try {
            mEMVOptV2.importPinInputStatus(mPinType, inputResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getCardInfo() {
        String[] tagList = {"5A", "5F24", "57", "5F34", "9F6B"};
        byte[] outData = new byte[1024];
        try {
            int len = mEMVOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagList, outData);
            if (len > 0) {
                byte[] data = new byte[len];
                System.arraycopy(outData, 0, data, 0, len);
                CardInfo cardInfo = KernelDataProcessUtil.getCardInfo(mPayDetail.cardType, data);
                mTradeData = KernelDataProcessUtil.fillTradeDataInfo(cardInfo, mTradeData);
            } else {
                LogUtil.e(Constant.TAG, "获取卡片信息的数据长度为负数 = " + len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getF055Data() {
        String[] tagList = {
                "50", "57", "5A", "5F24", "5F2A", "5F34", "82", "84", "8A", "95", "9A", "9B", "9C", "4F",
                "9F02", "9F03", "9F06", "9F08", "9F09", "9F10", "9F1A", "9F1E", "9F26", "9F27",
                "9F33", "9F34", "9F35", "9F36", "9F37", "9F41", "9F63", "9F6B",
                "9F0E", "9F0F", "9F0D", "9F1A", "9F1E", "9F5B", "9F6E",
                "DF02", "FF30", "DF31", "FF31",
        };
        byte[] outData = new byte[2048];
        try {
            int len = mEMVOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagList, outData);
            if (len > 0) {
                byte[] data = new byte[len];
                System.arraycopy(outData, 0, data, 0, len);
                mTradeData = KernelDataProcessUtil.readKernelData(data, mTradeData);
            } else {
                LogUtil.e(Constant.TAG, "获取55域的数据长度为负数 = " + len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getPayWaveData() {
        String[] tagList = {
                "9F66"
        };
        byte[] dataOut = new byte[1024];
        try {
            int len = mEMVOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYWAVE, tagList, dataOut);
            if (len > 0) {
                byte[] bytes = Arrays.copyOf(dataOut, len);
                String hexStr = ByteUtil.bytes2HexStr(bytes);
                Map<String, TLV> map = TLVUtils.builderTLVMap(hexStr);
                LogUtil.e(Constant.TAG, "getPayWaveData :" + map);
            } else {
                LogUtil.e(Constant.TAG, "获取payWave的数据长度为负数 = " + len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void keyMap(String str, PinPadDataV2 data) {
        data.keyMap = new byte[64];
        for (int i = 0, j = 0; i < 12; i++, j++) {
            if (i == 9) {
                data.keyMap[i] = 0x0C;
                j--;
            } else if (i == 11) {
                data.keyMap[i] = 0x0D;
                j--;
            } else {
                data.keyMap[i] = (byte) str.charAt(j);
            }
        }
    }

    private String interceptCardNo(String cardNo) {
        int length = cardNo.length();
        String s1 = cardNo.substring(0, 6);
        String s2 = cardNo.substring(length - 4, length);
        return s1 + "******" + s2;
    }

    private void showListDialog(List<EMVCandidateV2> list) {
        if (mListDialog == null) {
            mListDialog = new ListDialog(this);
            mListDialog.setTitleText(R.string.index_select_app);
            mListDialog.setCancelable(true);
            mListDialog.setCanceledOnTouchOutside(true);
        }
        List<String> tempList = new ArrayList<>();
        for (EMVCandidateV2 emvCandidateV2 : list) {
            tempList.add(emvCandidateV2.aid);
        }
        mListDialog.setData(tempList);
        mListDialog.setOnItemClickListener(
                this::importAppSelect
        );
        try {
            mListDialog.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void dismissListDialog() {
        if (mListDialog != null) {
            mListDialog.dismiss();
        }
    }


}
